home *** CD-ROM | disk | FTP | other *** search
- //********************************************************************
- // LISTFILE.CPP - Handle ListFile display, searching, etc.
- //
- // Copyright (c) 1996 Daniel D. Miller
- //
- // Last Update: 09-04-95 11:17pm
- //
- // Compile with makefile
- //
- //********************************************************************
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include "intsum.hpp"
- #include "err_exit.hpp"
- #include "keycodes.h"
- // #include <memcheck.h>
-
- static char srchstr[81] ;
-
- //*****************************************************************
- static void fill_list_buffers(fpos_t pos);
- static int search_list_buffers(void);
- static void search_list_file(void);
- static void back_up_list1(void);
-
- //*****************************************************************
- void process_list_file(int list_mode, char *save_file)
- {
- char sfile[128], sname[13] ;
- char lstr[sizeof(sum_conv)+1] ;
- unsigned j, ref_bfr ;
-
- int_sum_line *iptr = (int_sum_line *) lstr ;
-
- dprints(0, 2, LOGO, list_header) ;
- dprints(0, 3, LOGO, list_dividerd) ;
-
- // initialize list-file variables which are not
- // otherwise later set up.
- list.offset = 0 ;
- list.cur_bfr = 0 ;
- list.hdptr[0] = 0L ;
-
- // figure out which line in ref file was selected
- ref_bfr = (unsigned) ref.cur_bfr ;
- unsigned currow = ref.offset + ivideo.currow - DATA_TOP ;
- if (currow > (ref.lines[0] + ref.lines[1]))
- return ;
- if (ref.cur_bfr == 0 && currow > ref.lines[0])
- {
- ref_bfr = 1 ;
- currow -= ref.lines[0] ;
- }
- else if (ref.cur_bfr == 1 && currow > ref.lines[1])
- return ;
-
- // read appropriate data into list-file struct.
- strcpy(lstr, ref.bfr[ref_bfr][currow].instr) ;
-
- if (iptr->file == ' ')
- {
- _makepath(sfile, ildrive, ilpath, "interrup", "lst") ;
- strcpy(sname,"interrup.lst") ;
- }
- else
- {
- char c2s[5] ;
- c2s[0] = iptr->file ;
- c2s[1] = NULL ;
- _makepath(sfile, ildrive, ilpath, "interrup", c2s) ;
- _makepath(sname, NULL, NULL, "interrup", c2s) ;
- }
-
- // determine file offset
- iptr->null_term = 0 ;
- fpos_t loffset = strtol(iptr->foffset, NULL, 16) ;
-
- // open the file
- lfile = fopen(sfile, "rb") ;
- if (lfile == NULL)
- error_exit(NO_READ_FILE, sfile) ;
-
- fill_list_buffers(loffset) ; // fill the list buffers
-
- // now, determine whether this is a "print topic" call
- // or a normal "display" call
- if (list_mode == 1)
- {
- // open the output file
- FILE* outfile = fopen(save_file, "wt") ;
- if (outfile == NULL)
- {
- strupr(save_file) ;
- sprintf(tempstr, "cannot open %s", save_file) ;
- message_show(tempstr) ;
- fclose(lfile) ;
- dprints(0, 2, LOGO, header) ;
- dprints(0, 3, LOGO, dividerd) ;
- return ;
- }
-
- // write the data into it
- ref_bfr = 0 ; // overloading this variable
- j=0 ;
- do {
- fprintf(outfile, "%s\n", list.bfr[ref_bfr][j].instr) ;
- if (++j > list.lines[ref_bfr])
- {
- j = 0 ;
- if (++ref_bfr == 2)
- {
- fill_list_buffers(list.tlptr[1]) ; // refill the list buffers
- ref_bfr = 0 ;
- }
- }
- }
- while (strncmp(list.bfr[ref_bfr][j].instr, "--------", 8) != 0) ;
-
- // close files and exit
- fclose(outfile) ;
- fclose(lfile) ;
- dprints(0, 2, LOGO, header) ;
- dprints(0, 3, LOGO, dividerd) ;
- return ;
- }
-
- // display current filename on screen
- dprints(1, 2, FILENAME, sname) ;
-
- // display the first buffer of data
- ivideo.currow = DATA_TOP ;
- display_list_file() ;
-
- // list-file keyboard handler
- srchstr[0] = 0 ; // reset the search string
- unsigned rtemp ;
- int count ;
- int done = 0 ;
- while (!done)
- {
- mark_cursor_line(ivideo.currow, SELECTED) ;
- unsigned indata = get_key() ;
- mark_cursor_line(ivideo.currow, MAIN_TEXT) ;
- switch (indata)
- {
- case Key_UP:
- scroll_list_down() ;
- break;
-
- case Key_PGUP:
- rtemp = ivideo.currow ;
- ivideo.currow = DATA_TOP ;
- for (j=0; j<window_rows; j++)
- scroll_list_down() ;
- ivideo.currow = rtemp ;
- break;
-
- case Key_DOWN:
- scroll_list_up() ;
- break;
-
- case Key_PGDN:
- rtemp = ivideo.currow ;
- ivideo.currow = screen_rows - 1 ;
- for (j=0; j<window_rows; j++)
- scroll_list_up() ;
- ivideo.currow = rtemp ;
- break;
-
- case Key_HOME:
- loffset = 0 ;
- fill_list_buffers(loffset) ;
- list.offset = 0 ;
- list.cur_bfr = 0 ;
- ivideo.currow = DATA_TOP ;
- display_list_file() ;
- break;
-
- case Key_END:
- // seek end of file
- fseek(lfile, 0L, SEEK_END) ;
- fgetpos(lfile, &loffset) ;
- loffset -= REV_SIZE ;
-
- // adjust input-file position, then
- // read one line and re-position file pointer to full line
- fsetpos(lfile, &loffset) ;
- count = seek_next_line(lfile) ;
- if (count < 0)
- error_exit(BAD_SEARCH, NULL) ;
- loffset += count ;
- fill_list_buffers(loffset) ;
-
- // now, figure out which line is top of (end of screen)
- if (list.lines[1] < window_rows)
- {
- list.cur_bfr = 0 ;
- list.offset = list.lines[0] + list.lines[1] - window_rows ;
- }
- else
- {
- list.cur_bfr = 1 ;
- list.offset = list.lines[1] - window_rows ;
- }
-
- ivideo.currow = DATA_TOP ;
- display_list_file() ;
- break;
-
- case Key_F1:
- case Key_h:
- case Key_H: // display help screen
- display_help() ;
- display_logo() ;
- dprints(0, 2, LOGO, list_header) ;
- display_list_file() ;
- break;
-
- case Key_F2:
- case Key_s:
- case Key_S: // search for string
- if (message_read("Enter string to search for: ", srchstr) == 0)
- {
- if (search_list_buffers() != 0)
- search_list_file() ;
- }
- // redraw current filename on screen
- dprints(0, 2, LOGO, list_header) ;
- dprints(1, 2, FILENAME, sname) ;
- break;
-
- case Key_F3:
- case Key_r:
- case Key_R: // repeat last string search
- if (strlen(srchstr) == 0)
- message_show("There is no current search string") ;
- else if (search_list_buffers() != 0)
- search_list_file() ;
- // redraw current filename on screen
- dprints(0, 2, LOGO, list_header) ;
- dprints(1, 2, FILENAME, sname) ;
- break;
-
- case Key_ESC:
- fclose(lfile) ;
- dprints(0, 2, LOGO, header) ;
- dprints(0, 3, LOGO, dividerd) ;
- done = 1 ;
- break;
-
- default:
- break;
- } // keyboard switch
- } // while not done
- }
-
- //*****************************************************************
- void fill_list_buffers(fpos_t pos)
- {
- // adjust input-file position
- fsetpos(lfile, &pos) ;
- list.hdptr[0] = pos ;
-
- // read data and fill list_list buffer 0
- list.lines[0] = fill_list_bfr(0) ; // fill forward buffer
-
- // read data and fill list_list buffer 1
- list.hdptr[1] = list.tlptr[0] ;
- list.lines[1] = fill_list_bfr(1) ; // fill aft buffer
- }
-
- //*****************************************************************
- // first, search current list buffer(s) starting at list.offset.
- //*****************************************************************
- int search_list_buffers(void)
- {
- unsigned sline = list.offset + (ivideo.currow - DATA_TOP) + 1 ;
- int srch_done ;
- // first, search list.bfr0 if active
- if (list.cur_bfr == 0)
- {
- srch_done = 0 ;
- if (sline <= list.lines[0])
- {
- while (!srch_done)
- {
- // If string is found, update buffers and move cursor
- if (strstri(list.bfr[0][sline].instr, srchstr) == 0)
- {
- list.offset = sline ;
- // I _think_ this is the correct position
- search.offset = sline ;
- list.offset = sline ;
-
- ivideo.currow = DATA_TOP ;
- display_list_file() ;
- return 0;
- }
- // string is not yet found; move along in buffer0
- // if at end of buffer, exit and try buffer 1.
- else if (++sline >= list.lines[0])
- {
- srch_done = 1 ;
- sline = 0 ;
- }
- } // while not done searching
- } // if first search line actually IS in bfr0
- // if search line lapses into bfr1, move there
- else
- {
- sline -= list.lines[0] ;
- }
- }
-
- // then, search list.bfr1 if active, and nothing found in 0
- if (list.lines[1] > 0)
- {
- srch_done = 0 ;
- while (!srch_done)
- {
- // If string is found, update buffers and move cursor
- if (strstri(list.bfr[1][sline].instr, srchstr) == 0)
- {
- search.offset = sline ;
- list.cur_bfr = 1 ;
- list.offset = sline ;
- ivideo.currow = DATA_TOP ;
- display_list_file() ;
- return 0;
- }
- // string is not yet found; move along in buffer1.
- // if at end of buffer, exit and try other buffers.
- else if (++sline >= list.lines[1])
- {
- srch_done = 1 ;
- sline = 0 ;
- }
- } // while not done searching
- } // if any lines are in buffer1, search it
-
- return -1 ;
- }
-
- //*****************************************************************
- // current buffers have already been searched, with nothing found.
- // Now, search list file starting at list.tlptr[1].
- //*****************************************************************
- void search_list_file(void)
- {
- // first, save current file pointer so it
- // can be restored if no match is found.
- fpos_t oldpos ;
- fgetpos(lfile, &oldpos) ;
-
- // position file pointer to current cursor position
- search.hdptr = list.tlptr[1] ;
- fsetpos(lfile, &search.hdptr) ;
- // move past it to current line (if possible)
-
- // fill the readbfr from list file
- unsigned rlines = fill_search_buffer(lfile) ;
- if (rlines == 0)
- {
- message_show("Your search string was not found") ;
- return ;
- }
-
- unsigned sline = 0 ;
- int srch_done = 0 ;
- while (!srch_done)
- {
- // If string is found, update buffers and move cursor
- if (strstri(search.bfr[sline].instr, srchstr) == 0)
- {
- // read real data from beginning of current block
- fill_list_buffers(search.hdptr) ;
-
- // I _think_ this is the correct position
- search.offset = sline ;
- list.offset = sline ;
- list.cur_bfr = 0 ;
-
- ivideo.currow = DATA_TOP ;
- display_list_file() ;
- srch_done = 1 ;
- }
- // string is not yet found; move along in readbfr.
- // if at end of buffer, read next buffer or fail.
- else if (++sline >= rlines)
- {
- search.hdptr = search.tlptr ;
- rlines = fill_search_buffer(lfile) ;
- if (rlines == 0)
- {
- // restore input-file position
- fsetpos(lfile, &oldpos) ;
- srch_done = -1 ;
- message_show("Your search string was not found") ;
- }
- else
- {
- sline = 0 ;
- }
- }
- } // while not done searching
- }
-
- //*****************************************************************
- void scroll_list_down(void)
- {
- // if cursor is NOT at top, move cursor
- if (ivideo.currow > DATA_TOP)
- {
- ivideo.currow-- ;
- }
- // if cursor IS at top, try to move up in current buffer
- else if (list.offset > 0) // scroll window down
- {
- list.offset-- ;
- display_list_file() ;
- }
- // if current buffer is 1, just move back to buffer 0
- else if (list.cur_bfr == 1)
- {
- list.cur_bfr = 0 ;
- list.offset = list.lines[0] - 1 ;
- display_list_file() ;
- }
- // if current buffer = 0, see if we're at beginning of file.
- // if so, do nothing; otherwise, try to read back in buffer,
- // after copying buffer 0 to buffer 1.
- else if (list.hdptr[0] > 0)
- {
- // copy buffer0 values to buffer1
-
- // swap the buffer pointers
- lines *b = list.bfr[0] ;
- list.bfr[0] = list.bfr[1] ;
- list.bfr[1] = b ;
-
- list.lines[1] = list.lines[0] ;
- list.hdptr[1] = list.hdptr[0] ;
- list.tlptr[1] = list.tlptr[0] ;
- // current buffer remains 0.
- // list.cur_bfr = 0 ;
-
- // then compute and read new data into buffer0
- fill_list_bfr_rev() ; // fill forward buffer
- if (list.offset > 0)
- list.offset-- ;
- display_list_file() ;
- }
- }
-
- //*****************************************************************
- void scroll_list_up(void)
- {
- // end_line is line number for NEXT line
- unsigned end_line = list.offset + window_rows ; // base-0
-
- // if still onscreen, just move cursor
- if (ivideo.currow+1 < screen_rows)
- {
- ivideo.currow++ ;
- }
-
- // end of screen...
- // see if there's still room in buffer to move cursor
- else if (end_line < list.lines[list.cur_bfr])
- // ^base-0 ^base-1
- {
- list.offset++ ;
- display_list_file() ;
- }
-
- // we are at end of buffer
-
- //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- // BUFFER 0
- //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- else if (list.cur_bfr == 0)
- // If we're in buffer0, we should be able to slop over
- // into buffer1, if there's any data in it.
- {
- // if we were previously in buffer0, but now (after
- // adding one line) we don't fit in buffer0+buffer1,
- // there were less than (screen_size) lines in buffer1,
- // which means we're at end of file (otherwise, we
- // would have read roughly 32Kbytes).
- //
- // NOTE: we do not currently handle scrolling
- // across multiple files.
- //
- if (end_line >= (list.lines[0] + list.lines[1]))
- {
- // do nothing for now...
- // Later, we'll add multiple-file support.
- }
- // If there is room in the two combined files, see if
- // moving to next line has thrown us COMPLETELY into buffer1.
- else if ((list.offset+1) == list.lines[0])
- {
- list.offset = 0 ;
- list.cur_bfr = 1 ;
- display_list_file() ;
- }
- // otherwise, we're overlapping two files,
- // which the list function supports internally.
- else
- {
- list.offset++ ;
- display_list_file() ;
- }
- }
-
- //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- // BUFFER 1
- //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- // if NOT at end of buffer 1, update array offset and redraw
- else if (end_line < list.lines[1])
- // ^base0 ^base1
- {
- list.offset++ ;
- display_list_file() ;
- }
- // if we reach end of buffer 1,
- // copy buffer 1 to buffer 0 and see if
- // there's more data to scroll into.
- else
- {
- back_up_list1() ;
- if (list.lines[1] > 0)
- {
- list.offset++ ;
- display_list_file() ;
- }
- }
- }
-
- //*****************************************************************
- void back_up_list1(void)
- {
- // swap the buffer pointers
- lines *b = list.bfr[0] ;
- list.bfr[0] = list.bfr[1] ;
- list.bfr[1] = b ;
- // copy buffer1 data to buffer0 struct
- list.lines[0] = list.lines[1] ;
- list.hdptr[0] = list.hdptr[1] ;
- list.tlptr[0] = list.tlptr[1] ;
- list.cur_bfr = 0 ;
- list.hdptr[1] = list.tlptr[0] ;
-
- // read new data into buffer1
- list.lines[1] = fill_list_bfr(1) ;
- }
-
- //*****************************************************************
- void display_list_file(void)
- {
- // buffer_left is 1-based
- unsigned j, buffer_left = list.lines[list.cur_bfr] - list.offset ;
- // ^base-1 ^base-1 ^base-0
-
- // if current buffer fits entirely onscreen
- if (window_rows <= buffer_left)
- {
- for (j=0; j<window_rows; j++)
- {
- dprints(0, DATA_TOP+j, MAIN_TEXT,
- list.bfr[list.cur_bfr][list.offset+j].instr) ;
- }
- }
- // if we're currently using buffer 0, just lop over into bfr 1
- // Fill any unused lines with blank lines.
- else if (list.cur_bfr == 0)
- {
- if (window_rows > (buffer_left + list.lines[1]))
- // ^base1 ^base1 ^base1
- {
- // draw remainder of buffer0
- for (j=0; j<buffer_left; j++)
- {
- dprints(0, DATA_TOP+j, MAIN_TEXT,
- list.bfr[0][list.offset+j].instr) ;
- }
- // draw all of buffer1
- unsigned new_top = DATA_TOP + buffer_left ;
- for (j=0; j<list.lines[1]; j++)
- {
- dprints(0, new_top++, MAIN_TEXT, list.bfr[1][j].instr) ;
- }
- // draw blank lines
- spaces[80] = 0 ;
- //for (j=new_top; j<screen_rows; j++)
- while (new_top < screen_rows)
- {
- dprints(0, new_top++, MAIN_TEXT, spaces) ;
- }
- spaces[80] = ' ' ;
- }
- else
- {
- for (j=0; j<buffer_left; j++)
- {
- dprints(0, DATA_TOP+j, MAIN_TEXT,
- list.bfr[0][list.offset+j].instr) ;
- }
- for (j=0; j<(window_rows-buffer_left); j++)
- {
- dprints(0, DATA_TOP+buffer_left+j, MAIN_TEXT,
- list.bfr[1][j].instr) ;
- }
- }
- }
- // we're at end of buffer 1; are we at EOF??
- else
- {
- // copy buffer1 to buffer0,
- // then refill buffer 1.
- back_up_list1() ;
-
- // recursively call this display routine
- display_list_file() ;
- }
- }
-
- //*****************************************************************
- // parse lines from input file.
- //*****************************************************************
- const unsigned TAB_SIZE = 8 ;
-
- unsigned fill_list_bfr(unsigned bfr_flag)
- {
- int done = 0 ;
- //lint -e740
- unsigned offseti = FP_OFF(readptr) ; // init value for byte tfr counter
- unsigned offsetf ;
- unsigned count = 0, j ;
-
- // fill the readbfr from list file
- unsigned rlines = fill_read_buffer(lfile) ;
- if (rlines == 0)
- return 0;
-
- // now, translate the read buffer into the list-list buffer
- unsigned lcount = 0 ; // output_buffer counter
- char *sptr = readptr ;
- while (!done)
- {
- unsigned slen = strlen(sptr) ;
-
- if (slen == 0) // insert a blank line
- {
- spaces[80] = 0 ;
- strcpy(list.bfr[bfr_flag][lcount].instr, spaces) ;
- spaces[80] = ' ' ;
- }
-
- // copy data to list buffer. strcpy() won't do because
- // TABs have to be converted from the input files.
- //strcpy(list.bfr[bfr_flag][lcount].instr, sptr) ;
- else
- {
- char* cptr = sptr ;
- j = 0 ;
- while (j < 80 && *cptr != 0)
- {
- switch (*cptr)
- {
- case TAB:
- do {
- if (j < 80)
- {
- list.bfr[bfr_flag][lcount].instr[j] = ' ' ;
- }
- j++ ;
- }
- while ((j % TAB_SIZE) != 0);
- cptr++ ; // strip the TAB char from input
- break;
-
- default:
- list.bfr[bfr_flag][lcount].instr[j++] = *cptr++ ;
- break;
- } // switch (input char)
- }
-
- // if input line is longer than 80 chars, skim ahead to EOL
- if (j == 80)
- {
- while (*cptr != 0) cptr++ ;
- }
- else
- {
- // pad short lines with spaces
- while (j < 80)
- {
- list.bfr[bfr_flag][lcount].instr[j++] = ' ' ;
- }
- }
- list.bfr[bfr_flag][lcount].instr[80] = 0 ; // NULL-term the line
-
- // point to next string in buffer
- sptr += slen ;
- } // copy line to list buffer, expanding TABs
-
- // skip NULLs, which were formerly CR/LF
- // Skipping ALL NULLs is not appropriate, as this
- // effectively deletes blank lines.
- // We should skip at most 2 NULLs, then add all
- // further NULL pairs as blank lines.
- if (*sptr == NULL) sptr++ ; // skip CR
- if (*sptr == NULL) sptr++ ; // skip LF
- count++ ;
- lcount++ ;
-
- //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- // Determine if we are at end of input data (count),
- // or if output buffer is full (lcount)
- //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- if (lcount == list_lines || count == rlines)
- {
- done = 1 ;
- // set tail-pointer variable in current list struct
- offsetf = FP_OFF(sptr) ; //lint !e740
- list.tlptr[bfr_flag] = list.hdptr[bfr_flag] + (offsetf - offseti) ;
- // adjust input-file position
- fpos_t pos = list.tlptr[bfr_flag] ;
- fsetpos(lfile, &pos) ;
- }
- } // while not done filling input buffer
-
- return count;
- }
-
- //*****************************************************************
- void fill_list_bfr_rev(void)
- {
- unsigned count ;
- int done, icount ;
-
- // make a copy of current line before overwriting it,
- // so we can find it again afterwards
- strcpy(oldstr, list.bfr[1][list.offset].instr) ;
- if (strlen(oldstr) == 0)
- error_exit(BAD_FORMAT, NULL) ;
-
- // figure out how far to back up the read pointer
- fpos_t pos = IFF (list.hdptr[0] > REV_SIZE)
- THENN (list.hdptr[0] - REV_SIZE)
- ELSSE 0 ;
-
- // now read one line and re-position file pointer to full line
- // (if we're at beginning of file, don't bother)
- if (pos > 0)
- {
- fsetpos(lfile, &pos) ;
- icount = seek_next_line(lfile) ;
- if (icount < 0)
- error_exit(BAD_SEARCH, NULL) ;
- pos += icount ;
- }
- fill_list_buffers(pos) ;
-
- // now that new buffers have been read,
- // seek to the current line and update list.offset
- count = 0 ;
- done = 0 ;
- while (!done)
- {
- if (strcmp(oldstr, list.bfr[0][count].instr) == 0)
- {
- list.offset = count ;
- done = 1 ;
- }
- else if (++count >= list.lines[0])
- error_exit(BAD_SEARCH, NULL) ;
- }
- }
-
-